package com.hzw.saas.common.pay;

import com.hzw.saas.common.pay.alipay.AliTradeExecutor;
import com.hzw.saas.common.pay.alipay.bean.AliPagePayReqContent;
import com.hzw.saas.common.pay.alipay.bean.AliQueryReqContent;
import com.hzw.saas.common.pay.bean.PayContent;
import com.hzw.saas.common.pay.bean.PayUrl;
import com.hzw.saas.common.pay.bean.QueryContent;
import com.hzw.saas.common.pay.bean.TradeStatus;
import com.hzw.saas.common.pay.enums.PayType;
import com.hzw.saas.common.pay.enums.TradeStatusEnum;
import com.hzw.saas.common.pay.exception.TradeException;
import com.hzw.saas.common.pay.unionpay.UnionPayExecutor;
import com.hzw.saas.common.pay.unionpay.bean.UnionPayReqContent;
import com.hzw.saas.common.pay.unionpay.bean.UnionQueryReqContent;
import lombok.extern.slf4j.Slf4j;

/**
 * 统一支付接口
 *
 * @author zzl
 * @since 2020-11-04
 */
@Slf4j
public class PayExecutor {

    /**
     * 页面跳转支付
     *
     * @param payContent 支付内容
     * @param payType    支付方式
     * @return pay url
     * @throws TradeException e
     */
    public static PayUrl pagePay(PayContent payContent, PayType payType) throws TradeException {
        try {
            String pageContent = null;
            switch (payType) {
                case ALI_PAY:
                    AliPagePayReqContent aliContent = AliPagePayReqContent.build()
                        .out_trade_no(payContent.getPayNo())
                        .total_amount(payContent.getTotalAmount())
                        .subject(payContent.getPayTitle())
                        .body(payContent.getPayBody())
                        .time_expire(payContent.getExpireDate());
                    pageContent = AliTradeExecutor.pagePay(aliContent);
                    break;
                case UNION_PAY:
                    UnionPayReqContent unionContent = new UnionPayReqContent();
                    unionContent.setOrderId(payContent.getPayNo());
                    unionContent.setTxnAmt(payContent.getTotalAmount());
                    unionContent.setTxnTime(payContent.getCreateTime());
                    pageContent = UnionPayExecutor.frontPay(unionContent);
                    break;
                case WECHAT_PAY:
                    // TODO: ZZL@2020-11-04 实现微信跳转支付
                    throw new TradeException("暂不支持微信支付");
            }
            return new PayUrl()
                .setPayType(payType.value())
                .setPayForm(pageContent);
        } catch (Exception e) {
            throw new TradeException(e);
        }
    }

    /**
     * 二维码支付
     *
     * @param payContent 支付内容
     * @param payType    支付类型
     * @param qrcodeWith 二维码宽度
     * @return pay url
     * @throws TradeException e
     */
    public static PayUrl qrcodePay(PayContent payContent, PayType payType, int qrcodeWith) throws TradeException {
        try {
            String pageContent = null;
            switch (payType) {
                case ALI_PAY:
                    AliPagePayReqContent aliContent = AliPagePayReqContent.build()
                        .out_trade_no(payContent.getPayNo())
                        .total_amount(payContent.getTotalAmount())
                        .subject(payContent.getPayTitle())
                        .body(payContent.getPayBody())
                        .time_expire(payContent.getExpireDate());
                    pageContent = qrcodeWith > 0 ? AliTradeExecutor.qrcodePay(aliContent, qrcodeWith) : AliTradeExecutor.qrcodePay(aliContent);
                    break;
                case UNION_PAY:
                    throw new TradeException("银联支付暂不支持二维码");
                case WECHAT_PAY:
                    // TODO: ZZL@2020-11-04 实现微信二维码支付
                    throw new TradeException("暂不支持微信支付");
            }
            return new PayUrl()
                .setPayType(payType.value())
                .setPayForm(pageContent);
        } catch (Exception e) {
            throw new TradeException(e);
        }
    }

    /**
     * 全平台查询订单状态，只返回已支付的结果
     *
     * @param queryContent
     * @return
     */
    public static TradeStatus query(QueryContent queryContent) {

        for (PayType value : PayType.values()) {
            try {
                TradeStatus status = query(queryContent, value);
                if (status.getTradeStatus() != null && status.getTradeStatus() != TradeStatusEnum.UNKNOWN && status.getTradeStatus() != TradeStatusEnum.WAIT_BUYER_PAY) {
                    return status;
                }
            } catch (TradeException e) {
                log.error("交易查询异常", e);
            }
        }
        TradeStatus tradeStatus = new TradeStatus();
        tradeStatus.setPayNo(queryContent.getPayNo());
        tradeStatus.setBizPayNo(queryContent.getBizPayNo());
        tradeStatus.setCreateTime(queryContent.getCreateTime());
        tradeStatus.setPayTime(queryContent.getPayTime());
        tradeStatus.setTradeStatus(TradeStatusEnum.UNKNOWN);
        return tradeStatus;
    }

    /**
     * 交易查询
     *
     * @param queryContent
     * @param payType
     * @return
     * @throws TradeException
     */
    public static TradeStatus query(QueryContent queryContent, PayType payType) throws TradeException {
        try {
            TradeStatus tradeStatus = new TradeStatus();
            switch (payType) {
                case ALI_PAY:
                    AliQueryReqContent aliContent = AliQueryReqContent.build()
                        .out_trade_no(queryContent.getPayNo());
                    tradeStatus = AliTradeExecutor.query(aliContent);
                    break;
                case UNION_PAY:
                    UnionQueryReqContent unionContent = new UnionQueryReqContent();
                    unionContent.setOrderId(queryContent.getPayNo());
                    unionContent.setTxnTime(queryContent.getCreateTime()); // 被查询的交易的订单发送时间
                    tradeStatus = UnionPayExecutor.query(unionContent);
                    break;
                case WECHAT_PAY:
                    throw new TradeException("暂不支持微信支付查询");
            }
            return tradeStatus;
        } catch (Exception e) {
            throw new TradeException(e);
        }
    }

}
